#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#define FPGA_I2C_DEVICE "/dev/i2c-10"
#define FPAG_I2C_SLAVE  0x30
#define MAX_READ_BUF    256

int fpga_i2c_read(unsigned char slave_addr, unsigned char *write_buf, int write_len, unsigned char *read_buf, int read_len)
{
    int ret;
    int fd = open(FPGA_I2C_DEVICE, O_RDWR);
    if(fd < 0)
    {
        printf("fail to open device : %s\n", FPGA_I2C_DEVICE);
        return -1;
    }

    if(ioctl(fd,I2C_SLAVE,FPAG_I2C_SLAVE) < 0)
    {
        printf("fail to set slave address : 0x%02x\n", FPAG_I2C_SLAVE);
        close(fd);
        return -1;        
    }

    struct i2c_rdwr_ioctl_data i2c_read_ioctl;

    struct i2c_msg msg[2] = { 
        [0] = {                                                         //第一个数据包
            .addr   = slave_addr,                                       //从机地址
            .flags  = 0,                                                //flags=0表示写操作,这里写的就是从机的寄存器地址
            .buf    = write_buf,                                        //要发送的数据
            .len    = write_len,
        },
        [1] = {                                                         //第二个数据包
            .addr   = slave_addr,  
            .flags  = 1,                                                //进行读的操作
            .buf    = read_buf, 
            .len    = read_len,
        },
    };

    i2c_read_ioctl.msgs = msg;
    i2c_read_ioctl.nmsgs = 2;

    ret = ioctl(fd, I2C_RDWR, &i2c_read_ioctl);

    if(ret < 0){
        perror("ioctl error/n");
        close(fd);
        return ret;
    }
    close(fd);
    return 0;
}

int fpga_i2c_write(unsigned char slave_addr, unsigned char reg, unsigned char *write_buf, int write_len)
{
    int ret;
    char write_buf_tmp[MAX_READ_BUF + 1]; 
    int fd = open(FPGA_I2C_DEVICE, O_RDWR);
    if(fd < 0)
    {
        printf("fail to open device : %s\n", FPGA_I2C_DEVICE);
        return -1;
    }

    if(ioctl(fd,I2C_SLAVE,FPAG_I2C_SLAVE) < 0)
    {
        printf("fail to set slave address : 0x%02x\n", FPAG_I2C_SLAVE);
        close(fd);
        return -1;        
    }

    write_buf_tmp[0] = reg;
    memcpy(&write_buf_tmp[1], write_buf, write_len);
    write(fd, write_buf_tmp, write_len + 1);

    close(fd);
    return 0;
}

int force_bmc_ready()
{
    char read_buf[MAX_READ_BUF];
    char write_buf[MAX_READ_BUF];
    int write_len = 0;
    int read_len = 0;
    unsigned char force_reg_val = 0;
    write_buf[0] = 0xa;
    write_len = 1;

    read_len = 1;
    fpga_i2c_read(FPAG_I2C_SLAVE, write_buf, write_len, read_buf, read_len);

    //printf("read data: 0x%0x\n", read_buf[0]);

    if(read_buf[0] & 0x80)
    {
        return 0;
    }
    else
    {
        write_buf[0] = read_buf[0] & (~ 0x1);
        write_len = 1;    
        fpga_i2c_write(FPAG_I2C_SLAVE, 0xa, write_buf, write_len );     

        write_buf[0] = read_buf[0] | 0x1;
        write_len = 1;    
        fpga_i2c_write(FPAG_I2C_SLAVE, 0xa, write_buf, write_len );         
        
        write_buf[0] = 0xa;
        write_len = 1;

        read_len = 1;
        fpga_i2c_read(FPAG_I2C_SLAVE, write_buf, write_len, read_buf, read_len);      

        if(!(read_buf[0] & 0x80))
        {
            printf("error!!, bmc not expect value,ret value: 0x%02x \n", read_buf[0]);
            return -1;
        }  
    }
    return 0;
}

int main(int argc, char** argv)
{
    char read_buf[MAX_READ_BUF];
    char write_buf[MAX_READ_BUF];
    int write_len = 0;
    int read_len = 0;
    int i = 0;

    force_bmc_ready();

    while(1)
    {
        force_bmc_ready();
        sleep(2);
    }
    // write_buf[0] = 0;
    // write_len = 1;

    // fpga_i2c_read(FPAG_I2C_SLAVE, write_buf, write_len, read_buf, MAX_READ_BUF);

    // if(read(fd,read_buf,sizeof(read_buf)) != sizeof(read_buf))
    // {
    //     printf("fail to read buf\n");
    //     return -1;
    // }

    // printf("read fpga data below...\n");
    // printf("------------------------------\n");
    // for(i = 0 ; i < MAX_READ_BUF ; i ++)
    // {
    //     printf("%02x ", read_buf[i]);
    //     if((i + 1) % 16 == 0)
    //     {
    //         printf("\n");
    //     }
    // }
    // printf("\n");
    // printf("------------------------------\n");

    // write_buf[0] = 0;
    // write_len = 1;    
    // fpga_i2c_write(FPAG_I2C_SLAVE, 0xa, write_buf, write_len );

    // write_buf[0] = 1;
    // write_len = 1;    
    // fpga_i2c_write(FPAG_I2C_SLAVE, 0xa, write_buf, write_len );


    // fpga_i2c_read(FPAG_I2C_SLAVE, write_buf, write_len, read_buf, MAX_READ_BUF);
    // printf("read fpga data below now...\n");
    // printf("------------------------------\n");
    // for(i = 0 ; i < MAX_READ_BUF ; i ++)
    // {
    //     printf("%02x ", read_buf[i]);
    //     if((i + 1) % 16 == 0)
    //     {
    //         printf("\n");
    //     }
    // }
    // printf("\n");
    // printf("------------------------------\n");

    return 0;
}





